using System.Text;

namespace Sanelib.CodeMaker
{
    public class DatabaseTableColumnSchema
    {
        public DataType DataType { get; set; }

        public string PropertyName { get; set; }
        public int PropertySize { get; set; }
        public bool IsUnique { get; set; }
        public bool IsIndexed { get; set; }
        public bool IsNull { get; set; }

        public string GetFromMapping()
        {
            switch (DataType)
            {
                case DataType.Guid:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Uid(\"" : "NullSafeUid(\"") + PropertyName + "\");";
                case DataType.Byte:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Byte(\"" : "NullSafeByte(\"") + PropertyName + "\");";
                case DataType.Boolean:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Bool(\"" : "NullSafeBool(\"") + PropertyName + "\");";
                case DataType.DateTime:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "DateTime(\"" : "NullSafeDateTime(\"") + PropertyName + "\");";
                case DataType.Enumeration:
                    return PropertyName + " = " + PropertyName + ".FromValue(dataReader.ReadNullSafeString(\"" + PropertyName + "Value\"));";
                case DataType.AnsiString:
                case DataType.AnsiStringFixedLength:
                case DataType.UnicodeString:
                case DataType.UnicodeStringFixedLength:
                    return PropertyName + " = dataReader.ReadNullSafeString(\"" + PropertyName + "\");";
                case DataType.Percentage:
                case DataType.Currency:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Decimal(\"" : "NullSafeDecimal(\"") + PropertyName + "\");";
                case DataType.Integer:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Int(\"" : "NullSafeInt(\"") + PropertyName + "\");";
                case DataType.LongInteger:
                    return PropertyName + " = dataReader.Read" + (IsNull ? "Long(\"" : "NullSafeLong(\"") + PropertyName + "\");";
                case DataType.Image:
                    return PropertyName + " = dataReader.ReadBytes(\"" + PropertyName + "\");";
            }

            return "//TODO: Add line for " + DataType + " " + PropertyName;
        }

        public string GetToMapping()
        {
            switch (DataType)
            {
                case DataType.Guid:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.UniqueIdentifier).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Byte:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.TinyInt).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Boolean:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.Bit).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.DateTime:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.DateTime).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Enumeration:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "Value\", SqlDbType.Char, 2).Value = (object)BaseEnumeration.GetDbNullSafe(" + PropertyName + ") ?? DBNull.Value;";
                case DataType.AnsiString:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.VarChar, " + PropertySize + ").Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.AnsiStringFixedLength:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.Char, " + PropertySize + ").Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.UnicodeString:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.NVarChar, " + PropertySize + ").Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.UnicodeStringFixedLength:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.NChar, " + PropertySize + ").Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Percentage:
                case DataType.Currency:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.Decimal).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Integer:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.Int).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.LongInteger:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.BigInt).Value = (object)" + PropertyName + " ?? DBNull.Value;";
                case DataType.Image:
                    return "cmd.Parameters.Add(\"@" + PropertyName + "\", SqlDbType.Image).Value = (object)" + PropertyName + " ?? DBNull.Value;";
            }

            return "//TODO: Add line for " + DataType + " " + PropertyName;
        }

        public string GetPropertyDeclaration(string appender, bool forView = false)
        {
            var sb = new StringBuilder();
                    
            switch (DataType)
            {
                case DataType.Guid:
                    return appender + "public Guid" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.AnsiString:
                case DataType.AnsiStringFixedLength:
                case DataType.UnicodeString:
                case DataType.UnicodeStringFixedLength:
                    return appender + "public string" + PropertyName + " { get; set; }";
                case DataType.Boolean:
                    return appender + "public bool" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.Byte:
                    return appender + "public byte" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.DateTime:
                    return appender + "public DateTime" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.Percentage:
                case DataType.Currency:
                    return appender + "public decimal" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.Integer:
                    return appender + "public int" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.LongInteger:
                    return appender + "public long" + (IsNull ? "? " : " ") + PropertyName + " { get; set; }";
                case DataType.Enumeration:
                    if (!forView) return appender + "public " + PropertyName + " " + PropertyName + " { get; set; }";
                    sb.AppendLine("");
                    sb.AppendLine(appender + "[JsonIgnore]");
                    sb.AppendLine(appender + "public " + PropertyName + " " + PropertyName + " { get; set; }");
                    sb.AppendFormat("{0}public string {1}Value {{ get {{ return {1} == null ? \"\" : {1}.Value; }} set {{ {1} = {1}.FromValue(value); }} }}", appender, PropertyName);
                    sb.AppendLine("");
                    sb.AppendFormat("{0}public string {1}Name {{ get {{ return {1} == null ? \"\" : {1}.DisplayName; }} set {{ {1} = {1}.FromDispaly(value); }} }}", appender, PropertyName);
                    sb.AppendLine("");
                    return sb.ToString();
                case DataType.Image:
                    if (forView) sb.AppendLine(appender + "[JsonIgnore]");
                    sb.AppendLine(appender + "public byte[] " + PropertyName + " { get; set; }");
                    return sb.ToString();
            }

            return "//TODO: Add line for " + DataType + " " + PropertyName;
        }

        public string GetColumnDeclaration()
        {
            switch (DataType)
            {
                case DataType.Guid:
                    return "[" + PropertyName + "] [uniqueidentifier] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.AnsiString:
                    return "[" + PropertyName + "] [varchar](" + PropertySize + ") " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.AnsiStringFixedLength:
                    return "[" + PropertyName + "] [char](" + PropertySize + ") " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.UnicodeString:
                    return "[" + PropertyName + "] [nvarchar](" + PropertySize + ") " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.UnicodeStringFixedLength:
                    return "[" + PropertyName + "] [nchar](" + PropertySize + ") " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Boolean:
                    return "[" + PropertyName + "] [bit] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Byte:
                    return "[" + PropertyName + "] [tinyint] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.DateTime:
                    return "[" + PropertyName + "] [datetime] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Percentage:
                    return "[" + PropertyName + "] [decimal](5,2) " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Currency:
                    return "[" + PropertyName + "] [decimal](9,2) " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Integer:
                    return "[" + PropertyName + "] [integer] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.LongInteger:
                    return "[" + PropertyName + "] [bigint] " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Enumeration:
                    return "[" + PropertyName + "Value] [char](2) " + (IsNull ? "NULL," : "NOT NULL,");
                case DataType.Image:
                    return "[" + PropertyName + "] [image] " + (IsNull ? "NULL," : "NOT NULL,");
            }

            return "--TODO: Add line for " + DataType + " " + PropertyName;
        }

        public string GetColumnParameter()
        {
            switch (DataType)
            {
                case DataType.Guid:
                    return ",@" + PropertyName + " [uniqueidentifier] " + (IsNull ? " = NULL" : "");
                case DataType.AnsiString:
                    return ",@" + PropertyName + " [varchar](" + PropertySize + ") " + (IsNull ? " = NULL" : "");
                case DataType.AnsiStringFixedLength:
                    return ",@" + PropertyName + " [char](" + PropertySize + ") " + (IsNull ? " = NULL" : "");
                case DataType.UnicodeString:
                    return ",@" + PropertyName + " [nvarchar](" + PropertySize + ") " + (IsNull ? " = NULL" : "");
                case DataType.UnicodeStringFixedLength:
                    return ",@" + PropertyName + " [nchar](" + PropertySize + ") " + (IsNull ? " = NULL" : "");
                case DataType.Boolean:
                    return ",@" + PropertyName + " [bit] " + (IsNull ? " = NULL" : "");
                case DataType.Byte:
                    return ",@" + PropertyName + " [tinyint] " + (IsNull ? " = NULL" : "");
                case DataType.DateTime:
                    return ",@" + PropertyName + " [datetime] " + (IsNull ? " = NULL" : "");
                case DataType.Percentage:
                    return ",@" + PropertyName + " [decimal](5,2) " + (IsNull ? " = NULL" : "");
                case DataType.Currency:
                    return ",@" + PropertyName + " [decimal](9,2) " + (IsNull ? " = NULL" : "");
                case DataType.Integer:
                    return ",@" + PropertyName + " [integer] " + (IsNull ? " = NULL" : "");
                case DataType.LongInteger:
                    return ",@" + PropertyName + " [bigint] " + (IsNull ? " = NULL" : "");
                case DataType.Enumeration:
                    return ",@" + PropertyName + "Value [char](2) " + (IsNull ? " = NULL" : "");
                case DataType.Image:
                    return ",@" + PropertyName + " [image] " + (IsNull ? " = NULL" : "");
            }

            return "--TODO: Add line for " + DataType + " " + PropertyName;
        }

    }
}